require('dotenv').config();
const axios = require('axios');
const nodemailer = require('nodemailer');

// 配置常量
const CONFIG = {
    EMAIL: {
        HOST: process.env.EMAIL_HOST || 'smtp.qq.com',
        PORT: process.env.EMAIL_PORT || 465,
        SECURE: true,
        FROM: `"系统监控" <${process.env.EMAIL_USER}>`,
        DEFAULT_RECIPIENT: process.env.DEFAULT_RECIPIENT || 'y511097@163.com'
    },
    HEALTH_CHECK: {
        TIMEOUT: 5000, // 5秒超时
        RETRY_COUNT: 1, // 失败重试次数
        SERVICES: [
            { name: 'intelligent', url: 'https://intelligent.fuxigen.com/api/health' },
            { name: 'reasonrag', url: 'https://reasonrag.fuxigen.com/api/health' },
            { name: 'fastrag', url: 'https://fastrag.fuxigen.com/api/health' },
            { name: 'fuxigen', url: 'https://www.fuxigen.com/api/fuxigen/health' }
        ]
    }
};

// 创建邮件传输器（单例模式）
let transporter;
const getTransporter = () => {
    if (!transporter) {
        transporter = nodemailer.createTransport({
            host: CONFIG.EMAIL.HOST,
            port: CONFIG.EMAIL.PORT,
            secure: CONFIG.EMAIL.SECURE,
            auth: {
                user: process.env.EMAIL_USER,
                pass: process.env.EMAIL_PASSWORD
            },
            pool: true, // 使用连接池
            maxConnections: 5, // 最大连接数
            maxMessages: 100 // 每个连接最大发送邮件数
        });
    }
    return transporter;
};

/**
 * 发送邮件函数（优化版）
 * @param {string} subject 邮件标题
 * @param {string|string[]} to 收件人地址
 * @param {string} content 邮件正文
 * @param {Object} [options] 可选参数
 * @param {string} [options.html] HTML格式内容
 * @param {Object[]} [options.attachments] 附件列表
 * @returns {Promise<Object>} 发送结果
 */
const sendEmail = async (subject, to = CONFIG.EMAIL.DEFAULT_RECIPIENT, content, options = {}) => {
    // 参数验证
    if (!subject || !content) {
        throw new Error('缺少必要参数: subject 或 content');
    }
    if (!to) {
        throw new Error('缺少收件人地址');
    }
    try {
        const mailOptions = {
            from: CONFIG.EMAIL.FROM,
            to: Array.isArray(to) ? to.join(', ') : to,
            subject,
            text: content,
            html: options.html || content,
            attachments: options.attachments || []
        };
        const info = await getTransporter().sendMail(mailOptions);
        return {
            success: true,
            messageId: info.messageId,
            timestamp: new Date().toISOString()
        };
    } catch (error) {
        console.error('邮件发送失败:', error);
        throw error; // 抛出错误由调用方处理
    }
};

/**
 * 检查单个服务健康状态（带重试机制）
 * @param {Object} service 服务配置
 * @returns {Promise<Object>} 检查结果
 */
const checkServiceHealth = async (service) => {
    let lastError;

    for (let attempt = 1; attempt <= CONFIG.HEALTH_CHECK.RETRY_COUNT + 1; attempt++) {
        const source = axios.CancelToken.source();
        const timeout = setTimeout(() => {
            source.cancel(`请求超时(${CONFIG.HEALTH_CHECK.TIMEOUT}ms)`);
        }, CONFIG.HEALTH_CHECK.TIMEOUT);

        try {
            const response = await axios.get(service.url, {
                cancelToken: source.token,
                validateStatus: () => true // 确保所有状态码都不会抛出错误
            });

            clearTimeout(timeout);

            if (response.status >= 200 && response.status < 300) {
                if (response.data.status !== 'ok') {
                    return {
                        name: service.name,
                        status: 'degraded',
                        details: response.data,
                        url: service.url
                    };
                }
                return {
                    name: service.name,
                    status: 'healthy',
                    url: service.url
                };
            }

            lastError = `HTTP ${response.status}: ${JSON.stringify(response.data)}`;
        } catch (error) {
            clearTimeout(timeout);
            lastError = axios.isCancel(error)
                ? error.message
                : error.response
                    ? `HTTP ${error.response.status}: ${JSON.stringify(error.response.data)}`
                    : error.message;
        }

        if (attempt <= CONFIG.HEALTH_CHECK.RETRY_COUNT) {
            await new Promise(resolve => setTimeout(resolve, 1000)); // 重试间隔1秒
        }
    }

    return {
        name: service.name,
        status: 'unhealthy',
        error: lastError,
        url: service.url
    };
};

/**
 * 服务健康检查（优化版）
 * @returns {Promise<Array>} 各服务检查结果
 */
const healthCheck = async () => {
    const startTime = Date.now();
    try {
        // 并行检查所有服务
        const results = await Promise.all(
            CONFIG.HEALTH_CHECK.SERVICES.map(service => checkServiceHealth(service))
        );
        // 筛选出有问题的服务
        const unhealthyServices = results.filter(s => s.status !== 'healthy');
        // 如果有问题服务，发送汇总报告
        if (unhealthyServices.length > 0) {
            const errorDetails = unhealthyServices.map(s =>
                `服务名称: ${s.name}\n状态: ${s.status}\n错误: ${s.error || 'N/A'}\nURL: ${s.url}\n`
            ).join('\n');

            await sendEmail(
                `服务健康检查报告 - ${unhealthyServices.length}个服务异常`,
                ['y511097@163.com','2865068912@qq.com'],
                `检测到以下服务异常:\n\n${errorDetails}`,
                {
                    html: `
                        <h2>服务健康检查报告</h2>
                        <p>检测到 <strong>${unhealthyServices.length}</strong> 个服务异常:</p>
                        <ul>
                            ${unhealthyServices.map(s => `
                                <li>
                                    <strong>${s.name}</strong> - ${s.status}<br>
                                    错误: ${s.error || 'N/A'}<br>
                                    URL: <a href="${s.url}">${s.url}</a>
                                </li>
                            `).join('')}
                        </ul>
                        <p>检查时间: ${new Date().toLocaleString()}</p>
                        <p>总耗时: ${Date.now() - startTime}ms</p>`
                }
            );
        }

        return {
            success: true,
            duration: Date.now() - startTime,
            healthy: results.filter(s => s.status === 'healthy').length,
            degraded: results.filter(s => s.status === 'degraded').length,
            unhealthy: unhealthyServices.length,
            results
        };
    } catch (error) {
        console.error('健康检查过程中发生错误:', error);

        await sendEmail(
            '服务健康检查系统错误',
            undefined,
            `健康检查系统自身发生错误:\n\n${error.stack || error.message}`
        );

        return {
            success: false,
            error: error.message,
            duration: Date.now() - startTime
        };
    }
};

module.exports = {
    sendEmail,
    healthCheck,
};